package com.gantzgulch.pairing.widgetcomparator;

import java.util.Comparator;

public class WidgetComparator implements Comparator<Widget> {

    private WidgetComparatorType type;

    public WidgetComparator(WidgetComparatorType type) {
        if (type == null) {
            throw new IllegalArgumentException("Type is required.");
        }
        this.type = type;
    }

    public int compare(Widget w1, Widget w2) {

        switch (type) {
        case PRICE:
            return compare(w1.getPrice(), w2.getPrice(), w1.getDescription(), w2.getDescription());
        case DESCRIPTION:
            return compare(w1.getDescription(), w2.getDescription(), w1.getManufacturer(), w2.getManufacturer());
        case MANUFACTURER:
            return compare(w1.getManufacturer(), w2.getManufacturer(), w1.getDescription(), w2.getDescription());

        }
        throw new IllegalStateException("Unknown comparator type : " + type);
    }

    private <S extends Object, T extends Object> int compare(Comparable<S> s1, S s2, Comparable<T> t1, T t2){
        int i = compare(s1, s2);
        if( i == 0 ){
            i = compare(t1, t2);
        }
        return i;
    }
    
    private <T extends Object> int compare(Comparable<T> o1, T o2) {

        if (o1 == o2) {
            return 0;
        }

        if (o1 == null) {
            return -1;
        }
        if (o2 == null) {
            return 1;

        }
        return o1.compareTo(o2);
    }

    public static enum WidgetComparatorType {
        PRICE("Sort by widget.getPrice(), widget.getDescription(), ascending, nulls sort first"), 
        DESCRIPTION("Sort by widget.getDescription(), widget.getManufacturer(), ascending, nulls sort first"), 
        MANUFACTURER("Sort by widget.getManufacturer(), widget.getDescription(), ascending, nulls sort first");

        private String description;

        private WidgetComparatorType(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }
}
